import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

import java.io.*;
import java.lang.instrument.Instrumentation;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * https://bbs.kanxue.com/thread-271052.htm
 * https://blog.novitechie.com/archives/idea-cracking
 * https://www.aliatry.com/2024/04/07/idea-agent-%E6%BF%80%E6%B4%BB%E5%8E%9F%E7%90%86
 * https://github.com/PastKing/Jetbrains-Key
 * https://github.com/NotoChen/Jetbrains-Help
 * https://github.com/iot/jetbra
 * https://www.xuzhengtong.com/2022/07/25/ja-netfilter/ja-netfilter-plugins-power
 * https://gitee.com/ja-netfilter
 * https://bbs.kanxue.com/thread-271578.htm
 */
public class JetBrains {
    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider()); // bcpkix-jdk18on
        generatorCrtKey(10);

        URL url = new URL("https://data.services.jetbrains.com/products?fields=code");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // String body = new Scanner(connection.getInputStream(), StandardCharsets.UTF_8.name()).useDelimiter("\\A").next();
        String body = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)).lines().collect(Collectors.joining());
        generatorLicense("Jetbrains", 10, Arrays.stream(body.split("},\\{")).map(x -> x.split(":")[1].replaceAll("[\"{}\\[\\]]", "")).toArray(String[]::new));

        generatorLicense("IDEA", 10, "II", "PCWMP", "PSI", "PDB");
        generatorLicense("CLion", 10, "CL", "PCWMP", "PSI");
        generatorPowerConf();
    }

    public static void premain(String args, Instrumentation inst) {
    }

    static void generatorCrtKey(long year) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        // 指定密钥长度为 4096，并用一个安全的随机数生成器来生成密钥
        keyPairGenerator.initialize(4096, new SecureRandom());
        KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 生成 RSA 密钥对
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        // System.out.println("-----BEGIN PRIVATE KEY-----\n" + Base64.getEncoder().encodeToString(privateKey.getEncoded()) + "\n-----END PRIVATE KEY-----");
        // System.out.println("-----BEGIN PUBLIC KEY-----\n" + Base64.getEncoder().encodeToString(publicKey.getEncoded()) + "\n-----END PUBLIC KEY-----");

        // KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode("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")));
        // publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode("MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApW49ygc1Xeh9UqjhoqgL9itgFuaViLKbJp0G3wFXBic0/0av9Yx4+dvC8tY9YsBjuC0Om06fFdWkrWPH+32Pzbg73sVD3ORZKrkUpQyjhViMjHN07hBOvcaf1YZlcufg0kwu3trvMAK7PeLHazuJnk2DWgfLgGLGDqeVf3ACuzFauRrj6+8DuXO41NGCYmnEk4rn+oGXPibWM0Hy2bya1qFzLo0A6w9o06uUOQxar58OKwb1sBTgk5QlESMHRz+Eiibh0csVTB2NbRN6rTDSILS8ybb+1S09vrGVgTRQCncYW8QJ2mQRYASza6OAKrxWTlJs8JTzWY5b7JfqZElZWwJ6WrbqRUZwiuYOSKHViy499cO+zOJCULjng1kHGfcbp9pxnz1dIy9T//2KLScjPsxTdl23XVtw9s93YQIv+QLfJVo2UT43NzgHbJ0kfVuKRFpUGEWeE78OL7K6rE32VGWeDDbEMEfaJMCjqUWtO5nFhnLLUJrzQCmo1qdU/4QXyVVSSyIAYe+n5rY0SzQRrU0v7UPqvDnewoGHgehaaAv2mav4u08zfAqjv1RMuYJyW8jjXDMoK3pwoi0zNfjdRtJf7mpebtAdqQOu8LBcyfWnzXYLTojNVbjgmpuXnK1ALNuoZIMKnfxrMoMV4WqRWpzYDbgMFR1wjGRURTFtINsCAwEAAQ==")));

        // 证书信息，用于构建 X.509 证书
        // 颁发者(issuerName)、主题(subjectName)、序列号(serialNumber)、有效期起始时间(notBefore)、有效期结束时间(notAfter)
        X500Name issuerName = new X500Name("CN=JetProfile CA"), subjectName = new X500Name("CN=Jetbrains");
        BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
        Date notBefore = Date.from(LocalDate.now().minusYears(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
        Date notAfter = Date.from(LocalDate.now().plusYears(year).atStartOfDay(ZoneId.systemDefault()).toInstant());
        // 创建证书构建器，包括了颁发者、主题、序列号、有效期、主题和公钥信息
        X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(issuerName, serialNumber, notBefore, notAfter, subjectName, SubjectPublicKeyInfo.getInstance(publicKey.getEncoded()));
        // 创建内容签名器，指定了使用 SHA256withRSA 算法对证书用私钥进行签名
        ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").build(privateKey);
        // 使用证书转换器(JcaX509CertificateConverter)将证书构建器以及签名者信息转换成 X.509 证书格式
        X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certBuilder.build(signer));
        // System.out.println("-----BEGIN CERTIFICATE-----\n" + Base64.getEncoder().encodeToString(cert.getEncoded()) + "\n-----END CERTIFICATE-----");

        // cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(Base64.getDecoder().decode("MIIEqjCCApKgAwIBAgIGAY/DcZtdMA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0EwHhcNMjMwNTI4MTYwMDAwWhcNMjUwNTI4MTYwMDAwWjAUMRIwEAYDVQQDDAlKZXRicmFpbnMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQClbj3KBzVd6H1SqOGiqAv2K2AW5pWIspsmnQbfAVcGJzT/Rq/1jHj528Ly1j1iwGO4LQ6bTp8V1aStY8f7fY/NuDvexUPc5FkquRSlDKOFWIyMc3TuEE69xp/VhmVy5+DSTC7e2u8wArs94sdrO4meTYNaB8uAYsYOp5V/cAK7MVq5GuPr7wO5c7jU0YJiacSTiuf6gZc+JtYzQfLZvJrWoXMujQDrD2jTq5Q5DFqvnw4rBvWwFOCTlCURIwdHP4SKJuHRyxVMHY1tE3qtMNIgtLzJtv7VLT2+sZWBNFAKdxhbxAnaZBFgBLNro4AqvFZOUmzwlPNZjlvsl+pkSVlbAnpatupFRnCK5g5IodWLLj31w77M4kJQuOeDWQcZ9xun2nGfPV0jL1P//YotJyM+zFN2XbddW3D2z3dhAi/5At8lWjZRPjc3OAdsnSR9W4pEWlQYRZ4Tvw4vsrqsTfZUZZ4MNsQwR9okwKOpRa07mcWGcstQmvNAKajWp1T/hBfJVVJLIgBh76fmtjRLNBGtTS/tQ+q8Od7CgYeB6FpoC/aZq/i7TzN8CqO/VEy5gnJbyONcMygrenCiLTM1+N1G0l/ual5u0B2pA67wsFzJ9afNdgtOiM1VuOCam5ecrUAs26hkgwqd/GsygxXhapFanNgNuAwVHXCMZFRFMW0g2wIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQBkffl8DL/0rwzTJRq82BkrUkKdso6qC6cr4ZLiD/l6+649YKKjBO69J1I8n1NQ0mFY4/JKi9RpEeYlfLhje5C3knqH+udr74DrBUCcBsbzyz/aAUtbiBuDdRDCI2kIPAZFtz79PiIdPrcPLYdnZBzCx4eNYO60dsJRM62Az82HPUJMDqmOxWM6mm6J3TBDnoKqJNbUqVtkyc8GZpa5z66PTpa+m8kxU2nz2XkZIdrA5FNHrIi72A1xZfyUgV/Kt0KEBy6x3k0ponnvKqrHDCpCI1P+KNrIp1eudzeK1TITe85/c8O/p42Ka3ouKvJ3c1c5XxtvZ3MgVVxE/aEqmGJuKKcdUfNTvYTyo+JPTtww++iImJl2wSceTA5k5rDEnd6p09DekkyJumhJFG8faylzI66x3L3W7taiQBTR7uXGEt5twGJf/HyVkU26bnGI8MGrYNdhXPNVpGWrUjhirh//ze2VY7hdILYW0P9XUmpLcz2ngYBdi3id5W6rjIaEm86gQMPZ9nUO1p7ViEwfLmS8lFhlLYRo0dl9nD+OqypSoLSOHySXDuhI/rYxTq9lJ4v83//4Db61Qv2BGO8hkKaK3zWXQQvsfQOzp0bJOA05fgKi65Uo0NrlQqDtaIBaXhGIvJWg/ZLjs7/BcJN47eGQlnApwqghREXcOyiCOEgLWg==")));

        if (Files.exists(Paths.get("ca.key"))) Files.delete(Paths.get("ca.key"));
        JcaPEMWriter pemWriter = new JcaPEMWriter(new FileWriter("ca.key"));
        pemWriter.writeObject(privateKey); // 将私钥写入 PEM 文件
        pemWriter.close();
        if (Files.exists(Paths.get("ca.crt"))) Files.delete(Paths.get("ca.crt"));
        pemWriter = new JcaPEMWriter(new FileWriter("ca.crt"));
        pemWriter.writeObject(cert); // 将证书写入 PEM 文件
        pemWriter.close();
    }

    static void generatorPowerConf() throws Exception {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(Files.newInputStream(Paths.get("ca.crt")));
        // x：证书的签名密文
        BigInteger x = new BigInteger(cert.getSignature());
        // y：证书指数，固定 65537
        BigInteger y = new BigInteger("65537");
        // z：内置根证书的公钥
        X509Certificate rootCertificate = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(ROOT_CERTIFICATE.getBytes(StandardCharsets.UTF_8)));
        RSAPublicKey publicKey = (RSAPublicKey) rootCertificate.getPublicKey();
        BigInteger z = publicKey.getModulus();
        // r：fake result
        RSAPublicKey certPublicKey = (RSAPublicKey) cert.getPublicKey();
        BigInteger r = x.modPow(certPublicKey.getPublicExponent(), certPublicKey.getModulus());
        System.out.printf("EQUAL,%s,%s,%s->%s%n", x, y, z, r);
    }

    // https://data.services.jetbrains.com/products?fields=code,name,description
    // https://plugins.jetbrains.com/plugin/16988-fast-request--api-buddy -> https://plugins.jetbrains.com/api/plugins/16988 -> purchaseInfo->productCode
    static void generatorLicense(String licenseId, long year, String... codes) throws Exception {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(Files.newInputStream(Paths.get("ca.crt")));

        String date = LocalDate.now().plusYears(year).format(DateTimeFormatter.ISO_DATE);
        byte[] licensePartBytes = new LicensePart(licenseId, codes, date).toString().getBytes(StandardCharsets.UTF_8);
        String licensePartBase64 = Base64.getEncoder().encodeToString(licensePartBytes);

        PEMParser pemParser = new PEMParser(new FileReader("ca.key"));
        KeyPair kp = new JcaPEMKeyConverter().getKeyPair((PEMKeyPair) pemParser.readObject());
        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initSign(kp.getPrivate());
        signature.update(licensePartBytes);
        String signatureBase64 = Base64.getEncoder().encodeToString(signature.sign());

        String certBase64 = Base64.getEncoder().encodeToString(cert.getEncoded());
        System.out.println(licenseId + "-" + licensePartBase64 + "-" + signatureBase64 + "-" + certBase64);
    }

    static class LicensePart {
        List<Product> products;
        int gracePeriodDays = 7;
        boolean autoProlongated = false, checkConcurrentUse = false, isAutoProlongated = true;
        String licenseId, licenseeName, licenseRestriction, assigneeName, assigneeEmail, metadata = "0120230914PSAX000005", hash = "TRIAL:-1920204289";

        @Override
        public String toString() {
            StringJoiner joiner = new StringJoiner(",", "{", "}");
            Arrays.stream(getClass().getDeclaredFields()).peek(f -> f.setAccessible(true)).forEach(f -> {
                try {
                    joiner.add("\"" + f.getName() + "\":" + (String.class.equals(f.getType()) ? "\"" + f.get(this) + "\"" : f.get(this)));
                } catch (IllegalAccessException ignored) {
                }
            });
            return joiner.toString();
        }

        public LicensePart(String licenseId, String[] codes, String date) {
            this.licenseId = licenseId;
            this.licenseeName = licenseId;
            this.assigneeName = licenseId;
            this.products = Arrays.stream(codes).map(code -> new Product(code, date)).collect(Collectors.toList());
        }
    }

    static class Product {
        boolean extended = true;
        String code, paidUpTo, fallbackDate;

        public Product(String code, String date) {
            this.code = code;
            this.paidUpTo = date;
            this.fallbackDate = date;
        }

        @Override
        public String toString() {
            StringJoiner joiner = new StringJoiner(",", "{", "}");
            // try { // 需要有 getXXX 方法
            //     for (PropertyDescriptor p : Introspector.getBeanInfo(getClass()).getPropertyDescriptors()) {
            //         Object v = p.getReadMethod().invoke(this);
            //         if (v != null) joiner.add("\"" + p.getName() + "\":" + (v instanceof String ? "\"" + v + "\"" : v));
            //     }
            // } catch (IntrospectionException | IllegalAccessException | InvocationTargetException ignored) {
            // }
            Arrays.stream(getClass().getDeclaredFields()).peek(f -> f.setAccessible(true)).forEach(f -> {
                try {
                    joiner.add("\"" + f.getName() + "\":" + (String.class.equals(f.getType()) ? "\"" + f.get(this) + "\"" : f.get(this)));
                } catch (IllegalAccessException ignored) {
                }
            });
            return joiner.toString();
        }
    }

    // https://github.com/JetBrains/marketplace-makemecoffee-plugin/blob/master/src/main/java/com/company/license/CheckLicense.java
    private static final String ROOT_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" +
        "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\n" +
        "-----END CERTIFICATE-----\n";
}